package case31

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
	"net/http"
	"strings"
)

func Test() {
	fmt.Println("🎯示例三十一：验证器-通用处理器")
	r := gin.Default()

	// 注册验证器
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("phone_u", phoneUValidator)
		v.RegisterValidation("phone_r", phoneRValidator)
	}

	// 使用校验错误处理中间件
	r.Use(ValidationMiddleware())

	// 简洁的处理器
	r.POST("/user", func(c *gin.Context) {
		var req UserRequest
		if err := BindAndValidate(c, &req); err != nil {
			// 错误已由中间件处理，直接返回
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"message": "成功",
			"data":    req,
		})
	})

	// 另一个示例 - 用户注册
	r.POST("/register", func(c *gin.Context) {
		var req RegisterRequest
		if err := BindAndValidate(c, &req); err != nil {
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"message": "注册成功",
			"data":    req,
		})
	})

	r.Run(":60000")
}

type UserRequest struct {
	Phone string `json:"phone" binding:"required,phone_u"`
}

type RegisterRequest struct {
	Username string `json:"username" binding:"required,min=3,max=20"`
	Email    string `json:"email" binding:"required,email"`
	Phone    string `json:"phone" binding:"required,phone_r"`
	Age      int    `json:"age" binding:"min=18"`
}

// 手机号验证器
var phoneUValidator validator.Func = func(fl validator.FieldLevel) bool {
	phone, ok := fl.Field().Interface().(string)
	if !ok {
		return false
	}
	// 简单的手机号格式验证
	return len(phone) == 11 && phone[0] == '1'
}

var phoneRValidator validator.Func = func(fl validator.FieldLevel) bool {
	phone, ok := fl.Field().Interface().(string)
	if !ok {
		return false
	}
	// 简单的手机号格式验证
	return len(phone) == 15 && phone[0] == '2'
}

// BindAndValidate 通用的绑定和验证方法
func BindAndValidate(c *gin.Context, obj interface{}) error {
	if err := c.ShouldBindJSON(obj); err != nil {
		// 将错误添加到 Gin 的上下文中，由中间件统一处理
		c.Error(err)
		return err
	}
	return nil
}

// ValidationMiddleware 校验错误处理中间件
func ValidationMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Next() // 先执行后续中间件和处理器

		// 检查是否有错误
		if len(c.Errors) > 0 {
			for _, ginErr := range c.Errors {
				// 处理 JSON 解析错误（包括空请求体）
				if isJSONParseError(ginErr.Err) {
					c.JSON(http.StatusBadRequest, gin.H{
						"message": "请求体必须是有效的 JSON 格式",
					})
					c.Abort()
					return
				}

				// 处理校验错误
				if validationErrors, ok := ginErr.Err.(validator.ValidationErrors); ok {
					errors := make(map[string]string)
					for _, fieldError := range validationErrors {
						fieldName := fieldError.Field()
						switch fieldError.Tag() {
						case "required":
							errors[fieldName] = "该字段为必填项"
						case "phone":
							errors[fieldName] = "手机号格式不正确"
						case "min":
							errors[fieldName] = fmt.Sprintf("字段长度不能小于%s", fieldError.Param())
						case "max":
							errors[fieldName] = fmt.Sprintf("字段长度不能大于%s", fieldError.Param())
						case "email":
							errors[fieldName] = "邮箱格式不正确"
						default:
							errors[fieldName] = "字段验证失败"
						}
					}

					c.JSON(http.StatusBadRequest, gin.H{
						"message": "参数验证失败",
						"data":    errors,
					})
					c.Abort()
					return
				}
			}

			// 处理其他类型的错误
			lastError := c.Errors.Last()
			c.JSON(http.StatusBadRequest, gin.H{
				"message": "参数验证失败",
				"data":    getFriendlyErrorMessage(lastError.Err),
			})
			c.Abort()
		}
	}
}

// isJSONParseError 判断是否为 JSON 解析错误
func isJSONParseError(err error) bool {
	if err == nil {
		return false
	}

	errMsg := err.Error()
	// 检查常见的 JSON 解析错误
	return strings.Contains(errMsg, "EOF") ||
		strings.Contains(errMsg, "unexpected end of JSON input") ||
		strings.Contains(errMsg, "invalid character") ||
		strings.Contains(errMsg, "json: cannot unmarshal")
}

// getFriendlyErrorMessage 获取友好的错误消息
func getFriendlyErrorMessage(err error) string {
	if err == nil {
		return "未知错误"
	}

	errMsg := err.Error()

	// 处理常见的错误类型
	switch {
	case strings.Contains(errMsg, "EOF"):
		return "请求体不能为空"
	case strings.Contains(errMsg, "unexpected end of JSON input"):
		return "JSON 格式不完整"
	case strings.Contains(errMsg, "invalid character"):
		return "JSON 格式错误"
	case strings.Contains(errMsg, "json: cannot unmarshal"):
		return "数据类型不匹配"
	default:
		return "请求参数错误"
	}
}

//
//// ValidationMiddleware 校验错误处理中间件
//func ValidationMiddleware() gin.HandlerFunc {
//	return func(c *gin.Context) {
//		c.Next() // 先执行后续中间件和处理器
//
//		// 检查是否有错误
//		if len(c.Errors) > 0 {
//			for _, ginErr := range c.Errors {
//				// 处理校验错误
//				if validationErrors, ok := ginErr.Err.(validator.ValidationErrors); ok {
//					errors := make(map[string]string)
//					for _, fieldError := range validationErrors {
//						fieldName := fieldError.Field()
//						switch fieldError.Tag() {
//						case "required":
//							errors[fieldName] = "该字段为必填项"
//						case "phone":
//							errors[fieldName] = "手机号格式不正确"
//						case "min":
//							errors[fieldName] = fmt.Sprintf("字段长度不能小于%s", fieldError.Param())
//						case "max":
//							errors[fieldName] = fmt.Sprintf("字段长度不能大于%s", fieldError.Param())
//						case "email":
//							errors[fieldName] = "邮箱格式不正确"
//						default:
//							errors[fieldName] = "字段验证失败"
//						}
//					}
//
//					c.JSON(http.StatusBadRequest, gin.H{
//						"message": "参数验证失败",
//						"data":    errors,
//					})
//					c.Abort()
//					return
//				}
//			}
//
//			// 处理其他类型的错误
//			lastError := c.Errors.Last()
//			c.JSON(http.StatusBadRequest, gin.H{
//				"error": lastError.Error(),
//			})
//			c.Abort()
//		}
//	}
//}
